Skip to content

fix(ui): drop nodeDepth partitioning so ELK derives lineage layers from edges#29224

Open
chirag-madlani wants to merge 4 commits into
mainfrom
fix-lineage-layout
Open

fix(ui): drop nodeDepth partitioning so ELK derives lineage layers from edges#29224
chirag-madlani wants to merge 4 commits into
mainfrom
fix-lineage-layout

Conversation

@chirag-madlani

@chirag-madlani chirag-madlani commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Describe your changes:

Fixes #29225

I dropped the nodeDepth-based ELK partitioning in the lineage graph and let ELK's layered algorithm derive layers from edge topology (with BRANDES_KOEPF node placement) because pinning each node to its single backend nodeDepth forced a multi-branch node into the column of its first depth while its other edges fanned out to different columns, producing a visually misaligned graph. The result is a cleaner, less rigid horizontal flow, and it also removes the partition-on-cyclic-graph crash source.

Type of change:

  • Bug fix

High-level design:

N/A — small change (3 files): removed the per-node elk.partitioning.partition hint in getELKLayoutedElements, and removed elk.partitioning.activate while switching elk.layered.nodePlacement.strategy from SIMPLE to BRANDES_KOEPF in ELKUtil. Focus/root centering is unaffected — it is handled separately by centerNodePosition, not by partitioning.

Tests:

Use cases covered

  • A lineage node reachable at multiple depths is placed at the layer that best fits all its edges instead of being locked to its first backend depth.

Unit tests

  • Updated ELKUtil.test.ts to match the new layout options (19/19 pass).

Backend integration tests

  • Not applicable (no backend API changes).

Ingestion integration tests

  • Not applicable (no ingestion changes).

Playwright (UI) tests

  • Not applicable (layout-only change to existing graph).

Manual testing performed

  1. Verified ELKUtil unit suite passes.
  2. Reviewed the lineage layout flow to confirm partitioning was the only consumer of nodeDepth in layout and that focus centering is independent.

UI screen recording / screenshots:

Issue:

Screen.Recording.2026-06-22.at.5.50.17.PM.mov

Fix:

Screen.Recording.2026-06-22.at.5.50.57.PM.mov

Checklist:

  • I have read the CONTRIBUTING document.
  • I have commented on my code, particularly in hard-to-understand areas.
  • I have added/updated tests and listed them above.

Greptile Summary

This PR fixes visual misalignment in the lineage graph by dropping ELK's partitioning mode (which pinned each node to its backend-provided nodeDepth column) and switching to the BRANDES_KOEPF node placement strategy with BALANCED alignment, letting ELK derive layer assignments from actual edge topology.

  • ELKUtil.ts: Removes elk.partitioning.activate and replaces SIMPLE node placement with BRANDES_KOEPF + elk.layered.nodePlacement.bk.fixedAlignment: BALANCED, with clear inline comments explaining each choice.
  • EntityLineageLayoutUtils.ts: Drops the per-node elk.partitioning.partition hint derived from node.data?.nodeDepth, removing the crash path on cyclic graphs.
  • ELKUtil.test.ts: All 19 unit tests updated to match the new layout options.

Confidence Score: 5/5

Safe to merge — the change removes a layout constraint that caused visual misalignment and cyclic-graph crashes, with no API or data model changes.

The diff is small and surgical: two layout option keys removed, two added, and corresponding test updates. The nodeDepth field on node data is simply ignored now rather than deleted, so no callsites break. The fallback in getELKLayoutedElements already handles ELK errors gracefully. Tests cover the new configuration exhaustively.

No files require special attention.

Important Files Changed

Filename Overview
openmetadata-ui/src/main/resources/ui/src/utils/EntityLineageLayoutUtils.ts Removes the per-node elk.partitioning.partition layoutOption derived from node.data?.nodeDepth, letting ELK infer layers purely from edge topology.
openmetadata-ui/src/main/resources/ui/src/utils/Lineage/Layout/ELKUtil/ELKUtil.ts Replaces SIMPLE node placement + elk.partitioning.activate with BRANDES_KOEPF + BALANCED alignment; well-commented to explain the visual motivation.
openmetadata-ui/src/main/resources/ui/src/utils/Lineage/Layout/ELKUtil/ELKUtil.test.ts Tests updated to assert BRANDES_KOEPF strategy, BALANCED alignment, and absence of elk.partitioning.activate; coverage is thorough (19 cases).

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph Before["Before (partitioning)"]
        A1[Node data\nnodeDepth=N] -->|per-node layoutOption| B1["elk.partitioning.partition = N"]
        B1 --> C1["ELK layered\n+ elk.partitioning.activate=true\n+ nodePlacement: SIMPLE"]
        C1 --> D1["Multi-branch node locked to\nits first backend depth column\n→ visual misalignment / cyclic crash"]
    end

    subgraph After["After (topology-driven)"]
        A2[Node data\nnodeDepth ignored] -->|no partition hint| B2["No per-node layoutOptions"]
        B2 --> C2["ELK layered\n+ nodePlacement: BRANDES_KOEPF\n+ bk.fixedAlignment: BALANCED"]
        C2 --> D2["ELK derives layers from\nedge topology → clean layout"]
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    subgraph Before["Before (partitioning)"]
        A1[Node data\nnodeDepth=N] -->|per-node layoutOption| B1["elk.partitioning.partition = N"]
        B1 --> C1["ELK layered\n+ elk.partitioning.activate=true\n+ nodePlacement: SIMPLE"]
        C1 --> D1["Multi-branch node locked to\nits first backend depth column\n→ visual misalignment / cyclic crash"]
    end

    subgraph After["After (topology-driven)"]
        A2[Node data\nnodeDepth ignored] -->|no partition hint| B2["No per-node layoutOptions"]
        B2 --> C2["ELK layered\n+ nodePlacement: BRANDES_KOEPF\n+ bk.fixedAlignment: BALANCED"]
        C2 --> D2["ELK derives layers from\nedge topology → clean layout"]
    end
Loading

Reviews (4): Last reviewed commit: "Merge branch 'main' into fix-lineage-lay..." | Re-trigger Greptile

…om edges

Pinning each node to its backend nodeDepth via elk.partitioning forced a
multi-branch node into the column of its first depth, misaligning its other
edges. Let ELK's layered algorithm derive layers from edge topology and use
BRANDES_KOEPF node placement for a cleaner, less rigid horizontal flow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chirag-madlani chirag-madlani requested a review from a team as a code owner June 19, 2026 13:47
@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

✅ PR checks passed

The linked issue has a description and all required Shipping project fields set. Thanks!

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 62%
62.32% (66848/107259) 44.16% (37493/84897) 45.44% (11232/24715)

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

🔴 Playwright Results — 1 failure(s), 11 flaky

✅ 4018 passed · ❌ 1 failed · 🟡 11 flaky · ⏭️ 84 skipped

Shard Passed Failed Flaky Skipped
✅ Shard 1 0 0 0 0
🟡 Shard 2 813 0 2 9
🔴 Shard 3 817 1 0 8
🟡 Shard 4 865 0 4 12
🟡 Shard 5 732 0 1 47
🟡 Shard 6 791 0 4 8

Genuine Failures (failed on all attempts)

Features/LineageExportPNGSnapshot.spec.ts › exported PNG includes edge lines between nodes (shard 3)
Error: �[2mexpect(�[22m�[31mBuffer�[39m�[2m).�[22mtoMatchSnapshot�[2m(�[22m�[32mexpected�[39m�[2m)�[22m failed

  Expected an image 6786px by 2520px, received 4986px by 2697px. 

  Snapshot: lineage-export-with-edges.png

🟡 11 flaky test(s) (passed on retry)
  • Features/ColumnBulkOperations.spec.ts › should not reset stats to zero while search request is loading (shard 2, 1 retry)
  • Features/DataQuality/ColumnLevelTests.spec.ts › Column Values To Be Not In Set (shard 2, 1 retry)
  • Pages/CustomProperties.spec.ts › Timestamp (shard 4, 1 retry)
  • Pages/CustomProperties.spec.ts › Entity Reference (shard 4, 2 retries)
  • Pages/CustomProperties.spec.ts › Set enum custom property on column and verify in UI (shard 4, 2 retries)
  • Pages/Domains.spec.ts › Verify domain data products count includes subdomain data products (shard 4, 1 retry)
  • Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts › Should remove user owner for knowledgeCenter (shard 5, 1 retry)
  • Pages/Lineage/DataAssetLineage.spec.ts › Column lineage for table -> container (shard 6, 1 retry)
  • Pages/Lineage/DataAssetLineage.spec.ts › Column lineage for searchIndex -> container (shard 6, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify lineage schema filter selection (shard 6, 1 retry)
  • Pages/UserDetails.spec.ts › Admin user can get all the roles hierarchy and edit roles (shard 6, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

BRANDES_KOEPF aligned a node to one child (top-biased), so a source with
children Y and Z sat parallel to Y instead of vertically centered. Switch
node placement to NETWORK_SIMPLEX, which assigns cross-axis coordinates by
minimizing weighted edge deviation, keeping a source balanced between its
children.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
NETWORK_SIMPLEX (and bare Brandes-Köpf) resolve a symmetric source's
placement to a top-aligned corner because all alignments tie on edge length,
so the source did not sit centered between its upstream/downstream branches.
Setting elk.layered.nodePlacement.bk.fixedAlignment to BALANCED averages the
four extreme alignments into a centroid, restoring vertical centering while
keeping edge-aware, straight-segment placement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chirag-madlani chirag-madlani enabled auto-merge (squash) June 22, 2026 15:34
@gitar-bot

gitar-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Removes nodeDepth partitioning from the lineage graph to resolve node misalignment and cyclic graph crashes, allowing ELK to derive layers from edge topology. Unit tests successfully updated to reflect the new layout configuration.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test Add this label to run secure Github workflows on PRs To release Will cherry-pick this PR into the release branch UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UI - enhance lineage rendering to show lineage without crossing edges

3 participants